目標:製作一個人類圖模組
輸入:生日日期時間
輸出:一 2x13(共 26 個數字)的人類圖矩陣
前幾天已經實作了 getDesignDate()
和 getPersonalityDate()
兩個函數,接下來需要一個從尤利安曆換算銘刻(imprint)的函數
getBodyGraph()
函數,用於取得完整人類圖資訊。getImprint()
函數,參數為一個尤利安曆時間。這邊我們利用了前幾天實作的兩個計算尤利安曆時間的函數 getDesignDate()
和 getPersonalityDate()
。// body-graph.service.ts
public getBodyGraph(birth: IDateTime): IBodyGraph {
return {
design: this.getImprint(this.getDesignDate(birth)),
personality : this.getImprint(this.getPersonalityDate(birth)),
};
}
public getImprint(jd: number): IImprint {
throw new Error('method not implemented');
}
getImprint()
函數。由於地球和南交點的計算需要太陽和北交點的位置(地球和南交點分別位於太陽和北交點在天球軌道上的正對面),這邊先暫時跳過計算。public getImprint(jd: number): IImprint {
const sun = this.getSubstructure(jd, SE_SUN);
const earth = /* to be implemented */;
const northNode = this.getSubstructure(jd, SE_TRUE_NODE);
const southNode = /* to be implemented */;
return {
sun,
earth,
moon: this.getSubstructure(jd, SE_MOON),
northNode,
southNode,
mercury: this.getSubstructure(jd, SE_MERCURY),
venus: this.getSubstructure(jd, SE_VENUS),
mars: this.getSubstructure(jd, SE_MARS),
jupiter: this.getSubstructure(jd, SE_JUPITER),
saturn: this.getSubstructure(jd, SE_SATURN),
uranus: this.getSubstructure(jd, SE_URANUS),
neptune: this.getSubstructure(jd, SE_NEPTUNE),
pluto: this.getSubstructure(jd, SE_PLUTO),
};
}
public getSubstructure(jd: number, planet: number): ISubstructure {
throw new Error('method not implemented');
}
getSubstructure()
函數,用於計算指定尤利安曆時間下,指定星球的位置。由於 swe_calc_ut()
出來的位置是天球經度,還需要一個函數來轉換為人類圖的閘門和爻。public getSubstructure(jd: number, planet: number): ISubstructure {
const calcResult = swe_calc_ut(jd, planet, this.SWE_IFLAG);
if (!('longitude' in calcResult)) {
this.assertSwissephResult(calcResult);
throw new Error('invalid result of swe_calc_ut()');
}
return this.getSubstructureFromLongitude(calcResult.longitude);
}
public getSubstructureFromLongitude(longitude: number): ISubstructure {
throw new Error('method not implemented');
}
NUM_GATES
總共 64 個閘門(對應易經六十四卦)NUM_LINES
一卦有 6 條爻線,總共 384 條NUM_DEGS
一個圓 360 度NUM_DEGS_PER_GATE
一個閘門 5.625 度NUM_DEGS_PER_LINE
一條爻線 0.9375 度INDEXED_GATES
按照時間(一年之間)依序對應的閘門號碼。人類圖的 41 閘門從水瓶座的 2 度開始對齊,完成一整年的週期(見附圖)private readonly SWE_IFLAG = SEFLG_JPLEPH | SEFLG_SPEED;
private readonly NUM_GATES = 64;
private readonly NUM_LINES = this.NUM_GATES * 6;
private readonly NUM_DEGS = 360;
private readonly NUM_DEGS_PER_GATE = this.NUM_DEGS / this.NUM_GATES;
private readonly NUM_DEGS_PER_LINE = this.NUM_DEGS / this.NUM_LINES;
private readonly INDEXED_GATES = [
'41', '19', '13', '49', '30', '55', '37', '63', '22', '36', '25',
'17', '21', '51', '42', '3', '27', '24', '2', '23', '8', '20',
'16', '35', '45', '12', '15', '52', '39', '53', '62', '56', '31',
'33', '7', '4', '29', '59', '40', '64', '47', '6', '46', '18',
'48', '57', '32', '50', '28', '44', '1', '43', '14', '34', '9',
'5', '26', '11', '10', '58', '38', '54', '61', '6',
] as const;
getSubstructureFromLongitude()
將天球經度轉換為人類圖的閘門和爻。public getSubstructureFromLongitude(longitude: number): ISubstructure {
// Gate 41 begins at 02º Aquarius while longitude 0 is at 0º Aries.
// The offset is 58º = (30º * 2) - 2º
// 30º per sign, there are 2 signs from Aquarius to Aries
const { x360 } = swe_degnorm(longitude + 58);
// gate
const gateIndex = Math.trunc(x360 / this.NUM_DEGS_PER_GATE);
const gate = this.INDEXED_GATES[gateIndex];
// line
const remain = x360 % this.NUM_DEGS_PER_GATE;
const line = String(Math.trunc(remain / this.NUM_DEGS_PER_LINE) + 1);
return { longitude, gate, line };
}
getOppositePosition()
:public getOppositePosition(longitude: number): number {
return swe_degnorm(longitude + 180).x360;
}
getImprint()
如下:public getImprint(jd: number): IImprint {
const sun = this.getSubstructure(jd, SE_SUN);
const earth = this.getSubstructureFromLongitude(
this.getOppositePosition(sun.longitude),
);
const northNode = this.getSubstructure(jd, SE_TRUE_NODE);
const southNode = this.getSubstructureFromLongitude(
this.getOppositePosition(northNode.longitude),
);
return {
sun,
earth,
moon: this.getSubstructure(jd, SE_MOON),
northNode,
southNode,
mercury: this.getSubstructure(jd, SE_MERCURY),
venus: this.getSubstructure(jd, SE_VENUS),
mars: this.getSubstructure(jd, SE_MARS),
jupiter: this.getSubstructure(jd, SE_JUPITER),
saturn: this.getSubstructure(jd, SE_SATURN),
uranus: this.getSubstructure(jd, SE_URANUS),
neptune: this.getSubstructure(jd, SE_NEPTUNE),
pluto: this.getSubstructure(jd, SE_PLUTO),
};
}
利用亞洲人類圖學院帶入 1990.01.01T00:00:00UTC
取得人類圖作為測資參考資料。
describe('BodyGraphService', () => {
it('getBodyGraph()', () => {
expect(
service.getBodyGraph({
year: 1990,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
millisecond: 0,
}),
).toEqual(
expect.objectContaining({
design: expect.objectContaining({
sun: expect.objectContaining({ gate: '48', line: '3' }),
earth: expect.objectContaining({ gate: '21', line: '3' }),
moon: expect.objectContaining({ gate: '5', line: '4' }),
northNode: expect.objectContaining({ gate: '30', line: '1' }),
southNode: expect.objectContaining({ gate: '29', line: '1' }),
mercury: expect.objectContaining({ gate: '6', line: '4' }),
venus: expect.objectContaining({ gate: '14', line: '3' }),
mars: expect.objectContaining({ gate: '48', line: '1' }),
jupiter: expect.objectContaining({ gate: '39', line: '1' }),
saturn: expect.objectContaining({ gate: '58', line: '5' }),
uranus: expect.objectContaining({ gate: '10', line: '4' }),
neptune: expect.objectContaining({ gate: '38', line: '1' }),
pluto: expect.objectContaining({ gate: '1', line: '1' }),
}),
personality: expect.objectContaining({
sun: expect.objectContaining({ gate: '38', line: '1' }),
earth: expect.objectContaining({ gate: '39', line: '1' }),
moon: expect.objectContaining({ gate: '30', line: '3' }),
northNode: expect.objectContaining({ gate: '13', line: '4' }),
southNode: expect.objectContaining({ gate: '7', line: '4' }),
mercury: expect.objectContaining({ gate: '61', line: '6' }),
venus: expect.objectContaining({ gate: '41', line: '5' }),
mars: expect.objectContaining({ gate: '9', line: '5' }),
jupiter: expect.objectContaining({ gate: '52', line: '2' }),
saturn: expect.objectContaining({ gate: '54', line: '1' }),
uranus: expect.objectContaining({ gate: '58', line: '3' }),
neptune: expect.objectContaining({ gate: '38', line: '3' }),
pluto: expect.objectContaining({ gate: '1', line: '5' }),
}),
}),
);
});
})
測試成功:
> jest
PASS src/body-graph/body-graph.service.spec.ts
BodyGraphService
✓ getDesignDate() (8 ms)
✓ getDesignDate() (3 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 1.334 s
Ran all test suites.
「人類圖基礎」系列功能,到這邊算是大功告成。
晚安,瑪卡巴卡。